1 : <?php
2 :
3 :
4 :
5 :
6 :
7 :
8 :
9 :
10 :
11 :
12 :
13 :
14 :
15 :
16 :
17 :
18 :
19 :
20 :
21 :
22 :
23 :
24 :
25 :
26 :
27 :
28 :
29 :
30 :
31 :
32 :
33 :
34 :
35 :
36 :
37 :
38 :
39 :
40 :
41 :
42 :
43 :
44 :
45 :
46 :
47 :
48 :
49 : class Requests_IRI
50 : {
51 :
52 :
53 :
54 :
55 :
56 : private $scheme = null;
57 :
58 :
59 :
60 :
61 :
62 :
63 : private $iuserinfo = null;
64 :
65 :
66 :
67 :
68 :
69 :
70 : private $ihost = null;
71 :
72 :
73 :
74 :
75 :
76 :
77 : private $port = null;
78 :
79 :
80 :
81 :
82 :
83 :
84 : private $ipath = '';
85 :
86 :
87 :
88 :
89 :
90 :
91 : private $iquery = null;
92 :
93 :
94 :
95 :
96 :
97 :
98 : private $ifragment = null;
99 :
100 :
101 :
102 :
103 :
104 :
105 :
106 : private $normalization = array(
107 : 'acap' => array(
108 : 'port' => 674
109 : ),
110 : 'dict' => array(
111 : 'port' => 2628
112 : ),
113 : 'file' => array(
114 : 'ihost' => 'localhost'
115 : ),
116 : 'http' => array(
117 : 'port' => 80,
118 : 'ipath' => '/'
119 : ),
120 : 'https' => array(
121 : 'port' => 443,
122 : 'ipath' => '/'
123 : ),
124 : );
125 :
126 :
127 :
128 :
129 :
130 :
131 : public function __toString()
132 : {
133 173 : return $this->get_iri();
134 : }
135 :
136 :
137 :
138 :
139 :
140 :
141 :
142 : public function __set($name, $value)
143 : {
144 133 : if (method_exists($this, 'set_' . $name))
145 133 : {
146 133 : call_user_func(array($this, 'set_' . $name), $value);
147 133 : }
148 : elseif (
149 : $name === 'iauthority'
150 0 : || $name === 'iuserinfo'
151 0 : || $name === 'ihost'
152 0 : || $name === 'ipath'
153 0 : || $name === 'iquery'
154 0 : || $name === 'ifragment'
155 0 : )
156 : {
157 0 : call_user_func(array($this, 'set_' . substr($name, 1)), $value);
158 0 : }
159 133 : }
160 :
161 :
162 :
163 :
164 :
165 :
166 :
167 : public function __get($name)
168 : {
169 :
170 :
171 308 : $props = get_object_vars($this);
172 :
173 : if (
174 308 : $name === 'iri' ||
175 133 : $name === 'uri' ||
176 133 : $name === 'iauthority' ||
177 : $name === 'authority'
178 133 : )
179 308 : {
180 307 : $return = $this->{"get_$name"}();
181 307 : }
182 133 : elseif (array_key_exists($name, $props))
183 : {
184 133 : $return = $this->$name;
185 133 : }
186 :
187 1 : elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))
188 : {
189 1 : $return = $this->$prop;
190 1 : }
191 :
192 0 : elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))
193 : {
194 0 : $return = $this->$prop;
195 0 : }
196 : else
197 : {
198 0 : trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
199 0 : $return = null;
200 : }
201 :
202 308 : if ($return === null && isset($this->normalization[$this->scheme][$name]))
203 308 : {
204 1 : return $this->normalization[$this->scheme][$name];
205 : }
206 : else
207 : {
208 308 : return $return;
209 : }
210 : }
211 :
212 :
213 :
214 :
215 :
216 :
217 :
218 : public function __isset($name)
219 : {
220 0 : if (method_exists($this, 'get_' . $name) || isset($this->$name))
221 0 : {
222 0 : return true;
223 : }
224 : else
225 : {
226 0 : return false;
227 : }
228 : }
229 :
230 :
231 :
232 :
233 :
234 :
235 : public function __unset($name)
236 : {
237 0 : if (method_exists($this, 'set_' . $name))
238 0 : {
239 0 : call_user_func(array($this, 'set_' . $name), '');
240 0 : }
241 0 : }
242 :
243 :
244 :
245 :
246 :
247 :
248 : public function __construct($iri = null)
249 : {
250 445 : $this->set_iri($iri);
251 445 : }
252 :
253 :
254 :
255 :
256 :
257 :
258 :
259 :
260 :
261 :
262 : public static function absolutize($base, $relative)
263 : {
264 164 : if (!($relative instanceof Requests_IRI))
265 164 : {
266 164 : $relative = new Requests_IRI($relative);
267 164 : }
268 164 : if (!$relative->is_valid())
269 164 : {
270 1 : return false;
271 : }
272 163 : elseif ($relative->scheme !== null)
273 : {
274 6 : return clone $relative;
275 : }
276 : else
277 : {
278 157 : if (!($base instanceof Requests_IRI))
279 157 : {
280 41 : $base = new Requests_IRI($base);
281 41 : }
282 157 : if ($base->scheme !== null && $base->is_valid())
283 157 : {
284 156 : if ($relative->get_iri() !== '')
285 156 : {
286 151 : if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)
287 151 : {
288 7 : $target = clone $relative;
289 7 : $target->scheme = $base->scheme;
290 7 : }
291 : else
292 : {
293 144 : $target = new Requests_IRI;
294 144 : $target->scheme = $base->scheme;
295 144 : $target->iuserinfo = $base->iuserinfo;
296 144 : $target->ihost = $base->ihost;
297 144 : $target->port = $base->port;
298 144 : if ($relative->ipath !== '')
299 144 : {
300 134 : if ($relative->ipath[0] === '/')
301 134 : {
302 11 : $target->ipath = $relative->ipath;
303 11 : }
304 123 : elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')
305 : {
306 4 : $target->ipath = '/' . $relative->ipath;
307 4 : }
308 119 : elseif (($last_segment = strrpos($base->ipath, '/')) !== false)
309 : {
310 117 : $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
311 117 : }
312 : else
313 : {
314 2 : $target->ipath = $relative->ipath;
315 : }
316 134 : $target->ipath = $target->remove_dot_segments($target->ipath);
317 134 : $target->iquery = $relative->iquery;
318 134 : }
319 : else
320 : {
321 10 : $target->ipath = $base->ipath;
322 10 : if ($relative->iquery !== null)
323 10 : {
324 5 : $target->iquery = $relative->iquery;
325 5 : }
326 5 : elseif ($base->iquery !== null)
327 : {
328 3 : $target->iquery = $base->iquery;
329 3 : }
330 : }
331 144 : $target->ifragment = $relative->ifragment;
332 : }
333 151 : }
334 : else
335 : {
336 5 : $target = clone $base;
337 5 : $target->ifragment = null;
338 : }
339 156 : $target->scheme_normalization();
340 156 : return $target;
341 : }
342 : else
343 : {
344 1 : return false;
345 : }
346 : }
347 : }
348 :
349 :
350 :
351 :
352 :
353 :
354 :
355 : private function parse_iri($iri)
356 : {
357 249 : $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
358 249 : if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
359 249 : {
360 249 : if ($match[1] === '')
361 249 : {
362 56 : $match['scheme'] = null;
363 56 : }
364 249 : if (!isset($match[3]) || $match[3] === '')
365 249 : {
366 61 : $match['authority'] = null;
367 61 : }
368 249 : if (!isset($match[5]))
369 249 : {
370 0 : $match['path'] = '';
371 0 : }
372 249 : if (!isset($match[6]) || $match[6] === '')
373 249 : {
374 220 : $match['query'] = null;
375 220 : }
376 249 : if (!isset($match[8]) || $match[8] === '')
377 249 : {
378 231 : $match['fragment'] = null;
379 231 : }
380 249 : return $match;
381 : }
382 : else
383 : {
384 0 : trigger_error('This should never happen', E_USER_ERROR);
385 0 : die;
386 : }
387 : }
388 :
389 :
390 :
391 :
392 :
393 :
394 :
395 : private function remove_dot_segments($input)
396 : {
397 229 : $output = '';
398 229 : while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
399 : {
400 :
401 64 : if (strpos($input, '../') === 0)
402 64 : {
403 8 : $input = substr($input, 3);
404 8 : }
405 64 : elseif (strpos($input, './') === 0)
406 : {
407 4 : $input = substr($input, 2);
408 4 : }
409 :
410 64 : elseif (strpos($input, '/./') === 0)
411 : {
412 22 : $input = substr($input, 2);
413 22 : }
414 61 : elseif ($input === '/.')
415 : {
416 6 : $input = '/';
417 6 : }
418 :
419 61 : elseif (strpos($input, '/../') === 0)
420 : {
421 34 : $input = substr($input, 3);
422 34 : $output = substr_replace($output, '', strrpos($output, '/'));
423 34 : }
424 58 : elseif ($input === '/..')
425 : {
426 6 : $input = '/';
427 6 : $output = substr_replace($output, '', strrpos($output, '/'));
428 6 : }
429 :
430 58 : elseif ($input === '.' || $input === '..')
431 : {
432 3 : $input = '';
433 3 : }
434 :
435 58 : elseif (($pos = strpos($input, '/', 1)) !== false)
436 : {
437 58 : $output .= substr($input, 0, $pos);
438 58 : $input = substr_replace($input, '', 0, $pos);
439 58 : }
440 : else
441 : {
442 6 : $output .= $input;
443 6 : $input = '';
444 : }
445 64 : }
446 229 : return $output . $input;
447 : }
448 :
449 :
450 :
451 :
452 :
453 :
454 :
455 :
456 :
457 :
458 : private function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
459 : {
460 :
461 291 : $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
462 :
463 :
464 291 : $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
465 :
466 :
467 :
468 291 : $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
469 :
470 :
471 291 : $position = 0;
472 291 : $strlen = strlen($string);
473 291 : while (($position += strspn($string, $extra_chars, $position)) < $strlen)
474 : {
475 30 : $value = ord($string[$position]);
476 :
477 :
478 30 : $start = $position;
479 :
480 :
481 30 : $valid = true;
482 :
483 :
484 :
485 30 : if (($value & 0xE0) === 0xC0)
486 30 : {
487 11 : $character = ($value & 0x1F) << 6;
488 11 : $length = 2;
489 11 : $remaining = 1;
490 11 : }
491 :
492 21 : elseif (($value & 0xF0) === 0xE0)
493 : {
494 6 : $character = ($value & 0x0F) << 12;
495 6 : $length = 3;
496 6 : $remaining = 2;
497 6 : }
498 :
499 15 : elseif (($value & 0xF8) === 0xF0)
500 : {
501 6 : $character = ($value & 0x07) << 18;
502 6 : $length = 4;
503 6 : $remaining = 3;
504 6 : }
505 :
506 : else
507 : {
508 9 : $valid = false;
509 9 : $length = 1;
510 9 : $remaining = 0;
511 : }
512 :
513 : if ($remaining)
514 30 : {
515 23 : if ($position + $length <= $strlen)
516 23 : {
517 22 : for ($position++; $remaining; $position++)
518 : {
519 22 : $value = ord($string[$position]);
520 :
521 :
522 22 : if (($value & 0xC0) === 0x80)
523 22 : {
524 20 : $character |= ($value & 0x3F) << (--$remaining * 6);
525 20 : }
526 :
527 : else
528 : {
529 2 : $valid = false;
530 2 : $position--;
531 2 : break;
532 : }
533 20 : }
534 22 : }
535 : else
536 : {
537 1 : $position = $strlen - 1;
538 1 : $valid = false;
539 : }
540 23 : }
541 :
542 :
543 : if (
544 :
545 : !$valid
546 :
547 30 : || $length > 1 && $character <= 0x7F
548 20 : || $length > 2 && $character <= 0x7FF
549 20 : || $length > 3 && $character <= 0xFFFF
550 :
551 :
552 20 : || ($character & 0xFFFE) === 0xFFFE
553 20 : || $character >= 0xFDD0 && $character <= 0xFDEF
554 20 : || (
555 :
556 20 : $character > 0xD7FF && $character < 0xF900
557 12 : || $character < 0xA0
558 14 : || $character > 0xEFFFD
559 14 : )
560 20 : && (
561 :
562 : !$iprivate
563 12 : || $character < 0xE000
564 6 : || $character > 0x10FFFD
565 6 : )
566 20 : )
567 30 : {
568 :
569 : if ($valid)
570 17 : $position--;
571 :
572 17 : for ($j = $start; $j <= $position; $j++)
573 : {
574 17 : $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
575 17 : $j += 2;
576 17 : $position += 2;
577 17 : $strlen += 2;
578 17 : }
579 17 : }
580 30 : }
581 :
582 291 : return $string;
583 : }
584 :
585 :
586 :
587 :
588 :
589 :
590 :
591 :
592 :
593 :
594 : private function remove_iunreserved_percent_encoded($match)
595 : {
596 :
597 :
598 36 : $bytes = explode('%', $match[0]);
599 :
600 :
601 :
602 :
603 36 : $string = '';
604 36 : $remaining = 0;
605 :
606 :
607 36 : for ($i = 1, $len = count($bytes); $i < $len; $i++)
608 : {
609 36 : $value = hexdec($bytes[$i]);
610 :
611 :
612 36 : if (!$remaining)
613 36 : {
614 :
615 36 : $start = $i;
616 :
617 :
618 36 : $valid = true;
619 :
620 :
621 36 : if ($value <= 0x7F)
622 36 : {
623 25 : $character = $value;
624 25 : $length = 1;
625 25 : }
626 :
627 16 : elseif (($value & 0xE0) === 0xC0)
628 : {
629 7 : $character = ($value & 0x1F) << 6;
630 7 : $length = 2;
631 7 : $remaining = 1;
632 7 : }
633 :
634 9 : elseif (($value & 0xF0) === 0xE0)
635 : {
636 3 : $character = ($value & 0x0F) << 12;
637 3 : $length = 3;
638 3 : $remaining = 2;
639 3 : }
640 :
641 6 : elseif (($value & 0xF8) === 0xF0)
642 : {
643 3 : $character = ($value & 0x07) << 18;
644 3 : $length = 4;
645 3 : $remaining = 3;
646 3 : }
647 :
648 : else
649 : {
650 3 : $valid = false;
651 3 : $remaining = 0;
652 : }
653 36 : }
654 :
655 : else
656 : {
657 :
658 11 : if (($value & 0xC0) === 0x80)
659 11 : {
660 10 : $remaining--;
661 10 : $character |= ($value & 0x3F) << ($remaining * 6);
662 10 : }
663 :
664 : else
665 : {
666 1 : $valid = false;
667 1 : $remaining = 0;
668 1 : $i--;
669 : }
670 : }
671 :
672 :
673 36 : if (!$remaining)
674 36 : {
675 :
676 : if (
677 :
678 : !$valid
679 :
680 34 : || $length > 1 && $character <= 0x7F
681 32 : || $length > 2 && $character <= 0x7FF
682 32 : || $length > 3 && $character <= 0xFFFF
683 :
684 32 : || $character < 0x2D
685 32 : || $character > 0xEFFFD
686 :
687 18 : || ($character & 0xFFFE) === 0xFFFE
688 15 : || $character >= 0xFDD0 && $character <= 0xFDEF
689 :
690 15 : || $character === 0x2F
691 15 : || $character > 0x39 && $character < 0x41
692 14 : || $character > 0x5A && $character < 0x61
693 13 : || $character > 0x7A && $character < 0x7E
694 13 : || $character > 0x7E && $character < 0xA0
695 12 : || $character > 0xD7FF && $character < 0xF900
696 12 : )
697 34 : {
698 27 : for ($j = $start; $j <= $i; $j++)
699 : {
700 27 : $string .= '%' . strtoupper($bytes[$j]);
701 27 : }
702 27 : }
703 : else
704 : {
705 9 : for ($j = $start; $j <= $i; $j++)
706 : {
707 9 : $string .= chr(hexdec($bytes[$j]));
708 9 : }
709 : }
710 34 : }
711 36 : }
712 :
713 :
714 :
715 : if ($remaining)
716 36 : {
717 2 : for ($j = $start; $j < $len; $j++)
718 : {
719 2 : $string .= '%' . strtoupper($bytes[$j]);
720 2 : }
721 2 : }
722 :
723 36 : return $string;
724 : }
725 :
726 : private function scheme_normalization()
727 : {
728 387 : if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])
729 387 : {
730 0 : $this->iuserinfo = null;
731 0 : }
732 387 : if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])
733 387 : {
734 1 : $this->ihost = null;
735 1 : }
736 387 : if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])
737 387 : {
738 2 : $this->port = null;
739 2 : }
740 387 : if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])
741 387 : {
742 12 : $this->ipath = '';
743 12 : }
744 387 : if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])
745 387 : {
746 0 : $this->iquery = null;
747 0 : }
748 387 : if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])
749 387 : {
750 0 : $this->ifragment = null;
751 0 : }
752 387 : }
753 :
754 :
755 :
756 :
757 :
758 :
759 :
760 : public function is_valid()
761 : {
762 369 : $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;
763 369 : if ($this->ipath !== '' &&
764 : (
765 314 : $isauthority && (
766 301 : $this->ipath[0] !== '/' ||
767 301 : substr($this->ipath, 0, 2) === '//'
768 301 : ) ||
769 : (
770 313 : $this->scheme === null &&
771 313 : !$isauthority &&
772 313 : strpos($this->ipath, ':') !== false &&
773 2 : (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))
774 2 : )
775 313 : )
776 314 : )
777 369 : {
778 1 : return false;
779 : }
780 :
781 368 : return true;
782 : }
783 :
784 :
785 :
786 :
787 :
788 :
789 :
790 :
791 : private function set_iri($iri)
792 : {
793 445 : static $cache;
794 445 : if (!$cache)
795 445 : {
796 1 : $cache = array();
797 1 : }
798 :
799 445 : if ($iri === null)
800 445 : {
801 145 : return true;
802 : }
803 444 : elseif (isset($cache[$iri]))
804 : {
805 319 : list($this->scheme,
806 319 : $this->iuserinfo,
807 319 : $this->ihost,
808 319 : $this->port,
809 319 : $this->ipath,
810 319 : $this->iquery,
811 319 : $this->ifragment,
812 319 : $return) = $cache[$iri];
813 319 : return $return;
814 : }
815 : else
816 : {
817 249 : $parsed = $this->parse_iri((string) $iri);
818 :
819 249 : $return = $this->set_scheme($parsed['scheme'])
820 249 : && $this->set_authority($parsed['authority'])
821 249 : && $this->set_path($parsed['path'])
822 249 : && $this->set_query($parsed['query'])
823 249 : && $this->set_fragment($parsed['fragment']);
824 :
825 249 : $cache[$iri] = array($this->scheme,
826 249 : $this->iuserinfo,
827 249 : $this->ihost,
828 249 : $this->port,
829 249 : $this->ipath,
830 249 : $this->iquery,
831 249 : $this->ifragment,
832 249 : $return);
833 249 : return $return;
834 : }
835 : }
836 :
837 :
838 :
839 :
840 :
841 :
842 :
843 :
844 : private function set_scheme($scheme)
845 : {
846 250 : if ($scheme === null)
847 250 : {
848 56 : $this->scheme = null;
849 56 : }
850 199 : elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
851 : {
852 0 : $this->scheme = null;
853 0 : return false;
854 : }
855 : else
856 : {
857 199 : $this->scheme = strtolower($scheme);
858 : }
859 250 : return true;
860 : }
861 :
862 :
863 :
864 :
865 :
866 :
867 :
868 :
869 : private function set_authority($authority)
870 : {
871 249 : static $cache;
872 249 : if (!$cache)
873 249 : $cache = array();
874 :
875 249 : if ($authority === null)
876 249 : {
877 61 : $this->iuserinfo = null;
878 61 : $this->ihost = null;
879 61 : $this->port = null;
880 61 : return true;
881 : }
882 192 : elseif (isset($cache[$authority]))
883 : {
884 158 : list($this->iuserinfo,
885 158 : $this->ihost,
886 158 : $this->port,
887 158 : $return) = $cache[$authority];
888 :
889 158 : return $return;
890 : }
891 : else
892 : {
893 36 : $remaining = $authority;
894 36 : if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
895 36 : {
896 2 : $iuserinfo = substr($remaining, 0, $iuserinfo_end);
897 2 : $remaining = substr($remaining, $iuserinfo_end + 1);
898 2 : }
899 : else
900 : {
901 34 : $iuserinfo = null;
902 : }
903 36 : if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
904 36 : {
905 6 : if (($port = substr($remaining, $port_start + 1)) === false)
906 6 : {
907 2 : $port = null;
908 2 : }
909 6 : $remaining = substr($remaining, 0, $port_start);
910 6 : }
911 : else
912 : {
913 30 : $port = null;
914 : }
915 :
916 36 : $return = $this->set_userinfo($iuserinfo) &&
917 36 : $this->set_host($remaining) &&
918 36 : $this->set_port($port);
919 :
920 36 : $cache[$authority] = array($this->iuserinfo,
921 36 : $this->ihost,
922 36 : $this->port,
923 36 : $return);
924 :
925 36 : return $return;
926 : }
927 : }
928 :
929 :
930 :
931 :
932 :
933 :
934 :
935 : private function set_userinfo($iuserinfo)
936 : {
937 37 : if ($iuserinfo === null)
938 37 : {
939 34 : $this->iuserinfo = null;
940 34 : }
941 : else
942 : {
943 3 : $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
944 3 : $this->scheme_normalization();
945 : }
946 :
947 37 : return true;
948 : }
949 :
950 :
951 :
952 :
953 :
954 :
955 :
956 :
957 : private function set_host($ihost)
958 : {
959 166 : if ($ihost === null)
960 166 : {
961 0 : $this->ihost = null;
962 0 : return true;
963 : }
964 166 : elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')
965 : {
966 16 : if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1)))
967 16 : {
968 15 : $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
969 15 : }
970 : else
971 : {
972 1 : $this->ihost = null;
973 1 : return false;
974 : }
975 15 : }
976 : else
977 : {
978 150 : $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
979 :
980 :
981 :
982 :
983 150 : $position = 0;
984 150 : $strlen = strlen($ihost);
985 150 : while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)
986 : {
987 5 : if ($ihost[$position] === '%')
988 5 : {
989 2 : $position += 3;
990 2 : }
991 : else
992 : {
993 4 : $ihost[$position] = strtolower($ihost[$position]);
994 4 : $position++;
995 : }
996 5 : }
997 :
998 150 : $this->ihost = $ihost;
999 : }
1000 :
1001 165 : $this->scheme_normalization();
1002 :
1003 165 : return true;
1004 : }
1005 :
1006 :
1007 :
1008 :
1009 :
1010 :
1011 :
1012 :
1013 : private function set_port($port)
1014 : {
1015 35 : if ($port === null)
1016 35 : {
1017 31 : $this->port = null;
1018 31 : return true;
1019 : }
1020 4 : elseif (strspn($port, '0123456789') === strlen($port))
1021 : {
1022 4 : $this->port = (int) $port;
1023 4 : $this->scheme_normalization();
1024 4 : return true;
1025 : }
1026 : else
1027 : {
1028 0 : $this->port = null;
1029 0 : return false;
1030 : }
1031 : }
1032 :
1033 :
1034 :
1035 :
1036 :
1037 :
1038 :
1039 : private function set_path($ipath)
1040 : {
1041 249 : static $cache;
1042 249 : if (!$cache)
1043 249 : {
1044 1 : $cache = array();
1045 1 : }
1046 :
1047 249 : $ipath = (string) $ipath;
1048 :
1049 249 : if (isset($cache[$ipath]))
1050 249 : {
1051 97 : $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
1052 97 : }
1053 : else
1054 : {
1055 155 : $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
1056 155 : $removed = $this->remove_dot_segments($valid);
1057 :
1058 155 : $cache[$ipath] = array($valid, $removed);
1059 155 : $this->ipath = ($this->scheme !== null) ? $removed : $valid;
1060 : }
1061 :
1062 249 : $this->scheme_normalization();
1063 249 : return true;
1064 : }
1065 :
1066 :
1067 :
1068 :
1069 :
1070 :
1071 :
1072 : private function set_query($iquery)
1073 : {
1074 248 : if ($iquery === null)
1075 248 : {
1076 219 : $this->iquery = null;
1077 219 : }
1078 : else
1079 : {
1080 30 : $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
1081 30 : $this->scheme_normalization();
1082 : }
1083 248 : return true;
1084 : }
1085 :
1086 :
1087 :
1088 :
1089 :
1090 :
1091 :
1092 : private function set_fragment($ifragment)
1093 : {
1094 249 : if ($ifragment === null)
1095 249 : {
1096 230 : $this->ifragment = null;
1097 230 : }
1098 : else
1099 : {
1100 19 : $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
1101 19 : $this->scheme_normalization();
1102 : }
1103 249 : return true;
1104 : }
1105 :
1106 :
1107 :
1108 :
1109 :
1110 :
1111 : private function to_uri($string)
1112 : {
1113 132 : static $non_ascii;
1114 132 : if (!$non_ascii)
1115 132 : {
1116 1 : $non_ascii = implode('', range("\x80", "\xFF"));
1117 1 : }
1118 :
1119 132 : $position = 0;
1120 132 : $strlen = strlen($string);
1121 132 : while (($position += strcspn($string, $non_ascii, $position)) < $strlen)
1122 : {
1123 0 : $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
1124 0 : $position += 3;
1125 0 : $strlen += 2;
1126 0 : }
1127 :
1128 132 : return $string;
1129 : }
1130 :
1131 :
1132 :
1133 :
1134 :
1135 :
1136 : private function get_iri()
1137 : {
1138 365 : if (!$this->is_valid())
1139 365 : {
1140 0 : return false;
1141 : }
1142 :
1143 365 : $iri = '';
1144 365 : if ($this->scheme !== null)
1145 365 : {
1146 306 : $iri .= $this->scheme . ':';
1147 306 : }
1148 365 : if (($iauthority = $this->get_iauthority()) !== null)
1149 365 : {
1150 299 : $iri .= '//' . $iauthority;
1151 299 : }
1152 365 : $iri .= $this->ipath;
1153 365 : if ($this->iquery !== null)
1154 365 : {
1155 39 : $iri .= '?' . $this->iquery;
1156 39 : }
1157 365 : if ($this->ifragment !== null)
1158 365 : {
1159 23 : $iri .= '#' . $this->ifragment;
1160 23 : }
1161 :
1162 365 : return $iri;
1163 : }
1164 :
1165 :
1166 :
1167 :
1168 :
1169 :
1170 : private function get_uri()
1171 : {
1172 132 : return $this->to_uri($this->get_iri());
1173 : }
1174 :
1175 :
1176 :
1177 :
1178 :
1179 :
1180 : private function get_iauthority()
1181 : {
1182 365 : if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
1183 365 : {
1184 299 : $iauthority = '';
1185 299 : if ($this->iuserinfo !== null)
1186 299 : {
1187 3 : $iauthority .= $this->iuserinfo . '@';
1188 3 : }
1189 299 : if ($this->ihost !== null)
1190 299 : {
1191 299 : $iauthority .= $this->ihost;
1192 299 : }
1193 299 : if ($this->port !== null)
1194 299 : {
1195 1 : $iauthority .= ':' . $this->port;
1196 1 : }
1197 299 : return $iauthority;
1198 : }
1199 : else
1200 : {
1201 159 : return null;
1202 : }
1203 : }
1204 :
1205 :
1206 :
1207 :
1208 :
1209 :
1210 : private function get_authority()
1211 : {
1212 0 : $iauthority = $this->get_iauthority();
1213 0 : if (is_string($iauthority))
1214 0 : return $this->to_uri($iauthority);
1215 : else
1216 0 : return $iauthority;
1217 : }
1218 : }
|